home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
t_jnos
/
j109lxa4.tgz
/
j109lxa4.tar
/
mailbox2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-04
|
42KB
|
1,842 lines
/* NOTE: because of size, the previous 'mailbox.c' has been
* split in 3 parts:
* mboxcmd.c, containing the 'mbox' subcommands,
* mailbox.c, containing some user mailbox commands, and
* mailbox2.c, containing the remaining user commands.
* 921125 - WG7J
*/
/* There are only two functions in this mailbox code that depend on the
* underlying protocol, namely mbx_getname() and dochat(). All the other
* functions can hopefully be used without modification on other stream
* oriented protocols than AX.25 or NET/ROM.
*
* SM0RGV 890506, most work done previously by W9NK
*
*** Changed 900114 by KA9Q to use newline mapping features in stream socket
* interface code; everything here uses C eol convention (\n)
*
* Numerous new commands and other changes by SM0RGV, 900120
*
* Gateway function now support outgoing connects with the user's call
* with inverted ssid. Users can connect to system alias as well...
* See also several mods in socket.c,ax25.c and others
* 11/15/91, WG7J/PA3DIS
*
* Userlogging, RM,VM and KM commands, and R:-line interpretation
* added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
*
* Inactivity timeout-disconnect added 920325 and later - WG7J
*
*/
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#ifdef MSDOS
#include <alloc.h>
#endif
#include <stdlib.h>
#include <string.h>
#ifdef UNIX
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "global.h"
#include "config.h"
#include "timer.h"
#include "proc.h"
#include "socket.h"
#include "usock.h"
#include "session.h"
#include "smtp.h"
#include "dirutil.h"
#include "telnet.h"
#include "ftp.h"
#include "ftpserv.h"
#include "commands.h"
#include "netuser.h"
#include "files.h"
#include "bm.h"
#include "pktdrvr.h"
#include "ax25.h"
#include "mailbox.h"
#include "ax25mail.h"
#include "nr4mail.h"
#include "cmdparse.h"
#include "mailfor.h"
#include "authent.h"
#ifdef MAILBOX
/* Log all gateway connects to the logfile - WG7J */
#define GWTRACE 1
/* By setting the fp to NULL, we can check in exitbbs()
* wether a tempfile has been closed or not - WG7J
*/
#define MYFCLOSE(x) { fclose(x); x = (FILE *) 0; }
/*
#define MBDEBUG
*/
extern time_t StartTime;
extern char Myalias[];
extern struct mbx *Mbox;
extern int BbsUsers;
extern int Totallogins;
extern char *Mtmsg;
extern int MAttended;
extern unsigned Maxlet;
extern char Mbpasswd[];
extern int MbSent;
extern int MbRead;
extern int MbRecvd;
#ifdef MBFWD
extern int MbForwarded;
#endif
extern char Noperm[];
extern char Nosock[];
extern char MboxId[];
extern char Loginbanner[];
extern char Howtoend[];
extern char CcLine[];
extern char Mbwelcome[];
extern char Mbbanner[];
extern char Mbwarning[];
extern char CurUsers[];
extern char MsgAborted[];
extern char Mbmenu[];
extern char Mbnrid[];
extern char Longmenu[];
extern void gw_alarm __ARGS((void *p));
extern void gw_input __ARGS((int s,void *notused,void *p));
extern void gw_superv __ARGS((int null,void *proc,void *p));
extern int dombusers __ARGS((int argc,char *argv[],void *p));
extern int dombpast __ARGS((int argc,char *argv[],void *p));
extern int doarea __ARGS((int argc,char *argv[],void *p));
extern int dombstatus __ARGS((int argc,char *argv[],void *p));
extern int dombmailstats __ARGS((int argc,char *argv[],void *p));
extern int dombcallbook __ARGS((int argc,char *argv[],void *p));
extern int dombarp __ARGS((int argc,char *argv[],void *p));
extern int doipheard __ARGS((int argc,char *argv[],void *p));
static void dombconnecthelp __ARGS((void));
extern int Mbnewmail;
extern int Usenrid;
extern int MBSecure;
extern int Mbsendquery;
#ifdef MBXTDISC
extern int32 Mbtdiscinit;
#endif
/*Enlighten them a bit!
*/
static
void
dombconnecthelp() {
#ifdef CONVERS
tputs("Syntax: 'C for Conference bridge\n"
#ifdef NETROM
" 'C <node>' for NET/ROM connects\n"
#endif
" 'C <port> <call>' for AX.25 connects\n"
#ifdef CALLBOOK
" 'CA to access internet callbook\n"
#endif
"\n");
#else /* CONVERS */
#ifdef NETROM
tputs("Syntax: 'C <node>' for NET/ROM connects\n"
" 'C <port> <call>' for AX.25 connects\n"
#else
tputs("Syntax: 'C <port> <call>' for AX.25 connects\n"
#endif /* NETROM */
#ifdef CALLBOOK
" 'CA to access internet callbook\n"
#endif
"\n");
#endif /* CONVERS */
}
#ifdef NETROM
int
#ifdef PROTOTYPES
dombnrnodes(int argc,char **argv,void *p)
#else
dombnrnodes(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
m = (struct mbx *)p;
if(argc < 2)
return doroutedump();
if(*argv[1] == '*')
argc = 1;
return dorouteinfo(argc,argv,p);
}
#endif
#ifdef MAILCMDS
int
#ifdef PROTOTYPES
dosid(int argc,char **argv,void *p)
#else
dosid(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
char *cp;
m = (struct mbx *)p;
if(argc == 1)
return 1;
if(argv[1][strlen(argv[1]) - 1] != ']') /* must be an SID */
return 1;
#ifdef notdef
if(m->stype == 'Z' && strncmp(argv[1],"cz",2) == 0) {
/* LAN-LINK's [ZCZ] */
m->sid |= MBX_LL;
return 0;
}
#endif
/* Other bbs's */
m->sid = MBX_SID;
/* Now check to see if this is an RLI board.
* As usual, Hank does it a bit differently from
* the rest of the world.
*/
if(m->stype == 'R' && strncmp(argv[1],"li",2) == 0)/* [RLI] at a minimum */
m->sid |= MBX_RLI_SID;
/* Or maybe it is F6FBB ? */
else if(m->stype == 'F')
m->sid |= MBX_FBB;
/* Check to see if the BBS supports a kludge called "hierarchical
* routing designators."
*
* No need to check for ']' -- it must be there or this is not
* a valid mbox id -- it is checked earlier (fix de OH3LKU)
*
* Sid format is [BBSTYPE-VERSION-OPTIONS]
* check for LAST -, to allow for version portion. - WG7J
*/
if((cp = strrchr(argv[1],'-')) != NULLCHAR) {
cp++;
/* Okay, now parse the options */
if((strchr(cp,'h') != NULLCHAR) && (strchr(cp,'$') != NULLCHAR))
m->sid |= MBX_HIER_SID;
if(strchr(cp,'m') != NULLCHAR)
m->sid |= MBX_MID;
}
return 0;
}
#endif
int
dombescape(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
m = (struct mbx *)p;
if(argc < 2){
tprintf("Escape is %s, Escape char: ",
(m->privs & NO_ESCAPE) ? "OFF" : "ON");
if(m->escape < 32)
tprintf("CTRL-%c\n",m->escape+'A'-1);
else
tprintf("'%c'\n",m->escape);
return 0;
}
if(strlen(argv[1]) > 1) {
if(isdigit(*argv[1]))
m->escape = (char) atoi(argv[1]);
else {
if( !strnicmp(argv[1],"OFF",3) || !strnicmp(argv[1],"dis",3) )
m->privs |= NO_ESCAPE;
else
m->privs &= ~NO_ESCAPE;
}
} else
m->escape = *argv[1];
return 0;
}
int
#ifdef PROTOTYPES
dodownload(int argc,char **argv,void *p)
#else
dodownload(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
FILE *fp;
char *file;
m = (struct mbx *)p;
file = pathname(m->path,argv[1]);
if(!permcheck(m->path,m->privs,RETR_CMD,file)){
tputs(Noperm);
mail_error("%s: download denied\n",m->name);
return 0;
}
#ifdef TIPMAIL
#ifdef XMODEM
if (m->stype=='X') {
if (m->type==TIP_LINK){ /* xmodem send tip only */
m->state = MBX_XMODEM_TX;
#ifdef MBXTDISC
/* disable the mbox inactivity timeout timer - WG7J */
stop_timer(&m->tdisc);
#endif
doxmodem('S',file,m);
return 0;
} else {
tputs("Xmodem on TIP connects only\n");
return 0;
}
}
#endif
#endif
m->state = MBX_DOWNLOAD;
if((fp = fopen(file,READ_TEXT)) == NULLFILE)
tprintf("Can't open \"%s\": %s\n",file,sys_errlist[errno]);
else {
#ifdef MBXTDISC
/* disable the mbox inactivity timeout timer - WG7J */
stop_timer(&m->tdisc);
#endif
if(m->stype == 'U'){ /* uuencode ? */
fclose(fp);
fp = fopen(file,READ_BINARY); /* assume non-ascii */
uuencode(fp,m->user,file);
} else
sendfile(fp,m->user,ASCII_TYPE,0);
}
free(file);
fclose(fp);
return 0;
}
int
#ifdef PROTOTYPES
dombupload(int argc,char **argv,void *p)
#else
dombupload(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
FILE *fp;
char *file;
m = (struct mbx *)p;
file = pathname(m->path,argv[1]);
if(!permcheck(m->path,m->privs,STOR_CMD,file)){
tputs(Noperm);
mail_error("%s: upload denied\n",m->name);
return 0;
}
#ifdef TIPMAIL
#ifdef XMODEM
if (m->stype=='X'){
if (m->type==TIP_LINK){ /* xmodem receive tip only */
m->state = MBX_XMODEM_RX;
#ifdef MBXTDISC
/* disable the mbox inactivity timeout timer - WG7J */
stop_timer(&m->tdisc);
#endif
doxmodem('R',file,m);
return 0;
} else {
tputs("Xmodem on TIP connects only\n");
return 0;
}
}
#endif
#endif
if((fp = fopen(file,WRITE_TEXT)) == NULLFILE){
tprintf("Can't create \"%s\": %s\n",file,sys_errlist[errno]);
free(file);
return 0;
}
log(m->user,"MBOX upload: %s",file);
m->state = MBX_UPLOAD;
tprintf("Send file, %s",Howtoend);
for(;;){
if(mbxrecvline(m) == -1){
unlink(file);
break;
}
if(*m->line == 0x01){ /* CTRL-A */
unlink(file);
tputs(MsgAborted);
break;
}
if(*m->line == CTLZ || !stricmp("/ex",m->line))
break;
fputs(m->line,fp);
#if !defined(UNIX) && !defined(__TURBOC__) && !defined(AMIGA)
/* Needed only if the OS uses a CR/LF
* convention and putc doesn't do
* an automatic translation
*/
if(putc('\r',fp) == EOF)
break;
#endif
if(putc('\n',fp) == EOF)
break;
}
free(file);
fclose(fp);
return 0;
}
int
#ifdef PROTOTYPES
dowhat(int argc,char **argv,void *p)
#else
dowhat(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
FILE *fp;
char *file;
m = (struct mbx *)p;
if(argc < 2)
file = strdup(m->path);
else
file = pathname(m->path,argv[1]);
if(!permcheck(m->path,m->privs,RETR_CMD,file)){
tputs(Noperm);
mail_error("%s: directory denied\n",m->name);
return 0;
}
m->state = MBX_WHAT;
if((fp = dir(file,1)) == NULLFILE)
tprintf("Can't read directory: \"%s\": %s\n",file,sys_errlist[errno]);
else {
#ifdef MBXTDISC
stop_timer(&m->tdisc);
#endif
sendfile(fp,m->user,ASCII_TYPE,0);
}
free(file);
fclose(fp);
return 0;
}
int
#ifdef PROTOTYPES
dozap(int argc,char **argv,void *p)
#else
dozap(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
char *file;
m = (struct mbx *)p;
file = pathname(m->path,argv[1]);
if(!permcheck(m->path,m->privs,DELE_CMD,file)){
tputs(Noperm);
mail_error("%s: zap denied\n",m->name);
return 0;
}
if(unlink(file))
tprintf("Zap failed: %s\n",sys_errlist[errno]);
log(m->user,"MBOX Zap: %s",file);
free(file);
return 0;
}
/*Password protection added - 920118, WG7J */
int
#ifdef PROTOTYPES
dosysop(int argc,char **argv,void *p)
#else
dosysop(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
int c;
int len,pwdc[5],i,valid=0;
char *cp;
extern struct cmds DFAR Cmds[];
m = (struct mbx *) p;
log(m->user,"MBOX: %s attempting SYSOP",m->name);
/*If you want anyone with the password to go sysop-mode
*comment out the next 4 line ! -WG7J
*/
if(!(m->privs & SYSOP_CMD)){
tputs(Noperm);
mail_error("%s: SYSOP denied !\n",m->name);
return 0;
}
/*only if set,
*check for the password before letting users proceed
*/
m->state = MBX_SYSOPTRY;
if((len = strlen(Mbpasswd)) != 0) {;
for (i=0;i<5;i++)
tprintf("%d ",(pwdc[i]=RANDOM(len))); /*print the random chars*/
tputc('\n');
while(1) {
c = mbxrecvline(m);
if(c == EOF || c == -2)
return 0;
if(*m->line == '\0')
break;
cp = m->line;
for(i=0;i<5;i++)
if(*cp++ != Mbpasswd[pwdc[i]])
break;
if (i == 5)
valid = 1;
}
if(!valid)
return 0;
}
log(m->user,"MBOX: %s is now SYSOP",m->name);
m->state = MBX_SYSOP;
tputs("\n\007Type 'exit' to return\n\nBe VERY carefull!!\n");
for(;;){
tputs("Net> ");
usflush(Curproc->output);
if(mbxrecvline(m) < 0)
break;
log(m->user,"MBOX sysop: %s",m->line);
if(cmdparse(Cmds,m->line,NULL) == -2)
break;
}
return 0;
}
/* Handle the "*** Done" command when reverse forwarding ends or the
* "*** LINKED to" command.
*/
int
#ifdef PROTOTYPES
dostars(int argc,char **argv,void *p)
#else
dostars(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
int anony = 1;
int founddigit = 0;
int oldprivs;
char *cp;
m = (struct mbx *)p;
/* The "*** LINKED to" command is only allowed to stations with
* SYSOP privileges to prevent others from obtaining the same.
*/
#ifdef notdef
if((m->privs & SYSOP_CMD) && argc == 4 && !strcmp(argv[1],"linked")) {
#endif
/* Allow 'linked to' from anyone, but reset SYSOP priviledges
* when the sysop-password is not set !
* Also try to set the new call !
* Inspired by Kurt, wb5bbw
* Check for the strange TEXNET linked message !
* 920220 - WG7J
*/
if((argc >= 4) && !strcmp(argv[1],"linked") && !strcmp(argv[2],"to") ) {
#ifdef GWTRACE
log(m->user,"MBOX LINKED: %s changed to %s",m->name,argv[3]);
#endif
strcpy(m->name,argv[3]);
oldprivs = m->privs; /*Save this !*/
/* Try to find the privileges of this user from the userfile */
if((m->privs = userlogin(m->name,NULLCHAR,&m->path,MBXLINE,
&anony)) == -1)
if((m->privs = userlogin("bbs",NULLCHAR,&m->path,
MBXLINE,&anony)) == -1)
if((m->privs = userlogin("anonymous",NULLCHAR,
&m->path,MBXLINE,&anony)) == -1){
m->privs = 0;
free(m->path);
m->path = NULLCHAR;
}
if(m->privs & EXCLUDED_CMD)
return domboxbye(0,NULLCHARP,p);
#ifdef AX25
/* Set the call */
for(cp=m->name;*cp != '\0';cp++)
if(isdigit((int)*cp))
break;
if(*cp != '\0')
founddigit = 1;
if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
m->privs &= ~AX25_CMD;
m->privs &= ~NETROM_CMD;
}
#else
m->privs &= ~AX25_CMD;
m->privs &= ~NETROM_CMD;
#endif
/*Kill ssid in name, if any*/
if((cp=strchr(m->name,'-')) != NULLCHAR)
*cp = '\0';
/*Check if sysop password is set,
*if not, disallow sysop privs no matter what !
*/
if(*Mbpasswd == '\0')
m->privs &= ~SYSOP_CMD;
/*Check to see if any of NO_READ,NO_SEND or NO_3PARTY were set,
*if so, dis-allow those no matter what
*(so that users cannot get priviledges by issuing a ***linked)
* 920220 - WG7J
*/
if(oldprivs & NO_SENDCMD)
m->privs |= NO_SENDCMD;
if(oldprivs & NO_READCMD)
m->privs |= NO_READCMD;
if(oldprivs & NO_3PARTY)
m->privs |= NO_3PARTY;
tprintf("Oh, hello %s.\n",m->name);
#ifdef MAILCMDS
changearea(m,m->name);
#endif
return 0;
}
if(argc > 1 && (m->sid & MBX_SID)) /* "*** Done" or similar */
return -2;
return -1;
}
#ifdef MAILCMDS
int
doarea(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
char *cp, *area;
FILE *fp;
char buf[MBXLINE];
m = (struct mbx *) p;
if(argc < 2){
#ifdef USERLOG
if(m->stype == 'N') {
listnewmail(m);
return 0;
}
#endif
area = strdup(m->area);
while((cp = strchr(area,'/')) != NULLCHAR)
*cp = '.';
tprintf("Current message area is: %s\n\n",area);
free(area);
tprintf("Available areas are:\n%-15s",m->name);
if(m->stype == 'F')
tputs(" Your private mail area\n");
else
tputc('\n');
if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE)
return 0;
if(m->stype == 'F')
sendfile(fp,m->user,ASCII_TYPE,0);
else {
/* send only the area names, not the description */
while(fgets(buf,MBXLINE,fp) != NULLCHAR) {
if(buf[0] != '#') { /* skip comments */
if((cp=strchr(buf,' ')) != NULLCHAR) {
*cp++ = '\n';
*cp = '\0';
}
if((cp=strchr(buf,'\t')) != NULLCHAR) {
*cp++ = '\n';
*cp = '\0';
}
tputs(buf);
}
}
tputs("\nType AF to get description of areas\n\n");
}
fclose(fp);
return 0;
}
if((m->privs & SYSOP_CMD) || strcmp(m->name,argv[1]) == 0){
/*Private mail-areas*/
changearea(m,argv[1]);
if(m->nmsgs){
if(!strcmp(m->name,m->area))
tputs("You have ");
else {
area = strdup(m->area);
while((cp = strchr(area,'/')) != NULLCHAR)
*cp = '.';
tprintf("%s: ",area);
free(area);
}
tprintf("%d message%s - %d new.\n", m->nmsgs,
m->nmsgs == 1 ? " " : "s ", m->newmsgs);
}
return 0;
}
if(isarea(argv[1])) {
/*Public mail areas*/
changearea(m,argv[1]);
area = strdup(m->area);
while((cp = strchr(area,'/')) != NULLCHAR)
*cp = '.';
#ifdef USERLOG
tprintf("%s: %d message%s - %d new\n\n",area,m->nmsgs,
m->nmsgs == 1 ? " " : "s ", m->newmsgs);
#else
tprintf("%s: %d message%s.\n", area, m->nmsgs,
m->nmsgs == 1 ? "" : "s");
#endif
free(area);
}
else
tprintf("No such message area: %s\n",argv[1]);
return 0;
}
/* subroutine to do the actual switch from one area to another */
/* USERLOGGING added by WG7J */
void
changearea(m,area)
struct mbx *m;
char *area;
{
char *cp;
#ifdef USERLOG
setlastread(m);
#endif
closenotes(m);
m->nmsgs = m->newmsgs = m->current = 0;
strcpy(m->area,area);
while((cp = strchr(m->area,'.')) != NULLCHAR)
*cp = '/';
while((cp = strchr(m->area,'\\')) != NULLCHAR)
*cp = '/';
#ifdef USERLOG
/* only read last read message-id if this is not a bbs,
* current area is a public area and not 'help'
* or area starts with 'sys'
*/
if(!(m->sid & MBX_SID))
if( (strcmp(area,"help") && isarea(area)) || !strncmp(m->area,"sys",3) )
getlastread(m);
#endif
scanmail(m);
}
#endif
int
dombtelnet(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
int s, len, i;
char dsocket[MAXSOCKSIZE];
struct sockaddr_in fsocket;
m = (struct mbx *) p;
fsocket.sin_family = AF_INET;
if(argc < 3)
fsocket.sin_port = IPPORT_TELNET;
else
fsocket.sin_port = atoip(argv[2]);
if((fsocket.sin_addr.s_addr = resolve(argv[1])) == 0){
tprintf(Badhost,argv[1]);
/* Free m->starmsg if set ! - WG7J */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
/* Only local telnets are are allowed to the unprivileged user */
/* The above is a security hole ! DO NOT allow this anymore ! - WG7J */
/* If the first letter of the command is 'C', then it was
* the CALL,QUERY,OPERATOR or CONVERS command !
* Allow these, no matter what.
* This way, you can give access to the Internet callserver,
* but disable all other telnets - WG7J
*/
if(*argv[0] != 'C') {
if(!(m->privs & TELNET_CMD) /* && !ismyaddr(fsocket.sin_addr.s_addr)*/ ){
tputs(Noperm);
mail_error("%s: Telnet denied\n",m->name);
/* Free m->starmsg if set ! - WG7J */
/* Shouldn't happen here, but just in case */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
}
if((s = socket(AF_INET,SOCK_STREAM,0)) == -1){
tputs(Nosock);
/* Free m->starmsg if set ! - WG7J */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
#ifdef GWTRACE
log(m->user,"MBOX TELNET: %s to %s:%d",m->name,argv[1],fsocket.sin_port);
#endif
if(fsocket.sin_port == IPPORT_TTYLINK) {
m->startmsg = mallocw(80);
len = MAXSOCKSIZE;
i = getpeername(m->user,dsocket,&len);
sprintf(m->startmsg,"*** Incoming call from %s@%s ***\n",
m->name,i != -1 ? psocket(dsocket): Hostname);
}
m->state = MBX_GATEWAY;
return gw_connect(m,s,(struct sockaddr *)&fsocket,SOCKSIZE);
}
int
#ifdef PROTOTYPES
dombfinger(int argc,char **argv,void *p)
#else
dombfinger(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
char *host, *user = NULLCHAR, buf[8], *newargv[3];
if(argc > 2){
tputs("Usage: F user@host or F @host or F user.\n");
return 0;
}
host = Hostname;
if(argc == 2){
if((host = strchr(argv[1], '@')) != NULLCHAR){
*host = '\0';
host++;
} else
host = Hostname;
user = argv[1];
}
m = (struct mbx *) p;
m->startmsg = mallocw(80);
if(user != NULLCHAR)
sprintf(m->startmsg,"%s\n",user);
else
strcpy(m->startmsg,"\n");
newargv[0] = "t";
newargv[1] = host;
sprintf(buf,"%d",IPPORT_FINGER);
newargv[2] = buf;
return dombtelnet(3,newargv,p);
}
/* Generic mbox gateway code. It sends and frees the contents of m->startmsg
* when the connection has been established unless it a null pointer.
*/
int
gw_connect(m,s,fsocket,len)
struct mbx *m;
int s;
struct sockaddr *fsocket;
int len;
{
int c;
char *cp, *cp1;
struct proc *child;
struct gwalarm *gwa;
char *node, *tocall, whereto[128], buf[80];
char temp[AXBUF];
struct nrroute_tab *rp;
sockmode(s,SOCK_ASCII);
child = newproc("gw supervisor",256,gw_superv,0,Curproc,m,0);
tputs("Trying...");
if(m->privs & NO_ESCAPE)
tputc('\n');
else {
tputs(" The escape character is: ");
if(m->escape < 32)
tprintf("CTRL-%c\n",m->escape+'A'-1);
else
tprintf("'%c'\n",m->escape);
}
usflush(Curproc->output);
/*find out where we're going to*/
tocall = strdup(psocket(fsocket));
if((cp1 = strchr(tocall,' ')) != NULLCHAR)
*cp1 = '\0';
#ifdef NETROM
if(fsocket->sa_family == AF_NETROM) {
/*find the node alias*/
setcall(temp,tocall);
rp = find_nrroute(temp);
node = strdup(rp->alias);
if((cp1 = strchr(node,' ')) != NULLCHAR)
*cp1 = '\0';
sprintf(whereto,"%s:%s",node,tocall);
free(node);
} else
#endif
strcpy(whereto,tocall);
free(tocall);
if(connect(s,(char *)fsocket,len) == -1){
if((cp = sockerr(s)) != NULLCHAR) {
switch(cp[0]) {
case 'R':
sprintf(buf,"%susy from",
(m->family == AF_NETROM)?"B":"*** b");
break;
case 'T':
if(m->family != AF_NETROM) {
sprintf(buf,"*** timeout with");
break;
}
default:
sprintf(buf,"%sailure with",
(m->family == AF_NETROM)?"F":"*** f");
break;
}
tprintf("%s%s %s\n\n",
(m->family == AF_NETROM) ? Mbnrid : "",buf,whereto);
}
shutdown(s,2); /* HB9RWM suggestion */
close_s(s);
killproc(child);
/* Free m->starmsg if set ! - WG7J */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
/* The user did not type the escape character */
killproc(child);
tprintf("%s%sonnected to %s\n",
(m->family == AF_NETROM) ? Mbnrid : "",
(m->family == AF_NETROM) ? "C" : "*** c",
whereto);
if(m->startmsg != NULLCHAR){
usputs(s,m->startmsg);
free(m->startmsg);
m->startmsg = NULLCHAR;
}
/* Since NOS does not flush the output socket after a certain
* period of time, we have to arrange that ourselves.
*/
gwa = (struct gwalarm *) mallocw(sizeof(struct gwalarm));
gwa->s1 = Curproc->output;
gwa->s2 = s;
set_timer(&gwa->t,2*1000L);
gwa->t.func = gw_alarm;
gwa->t.arg = (void *) gwa;
start_timer(&gwa->t);
/* Fork off the receive process */
child = newproc("gw in",1024,gw_input,s,m,Curproc,0);
for(;;){
if((c = recvchar(Curproc->input)) == EOF)
break;
/* Only check ESCAPE char if that is currently turned on */
if( !(m->privs & NO_ESCAPE) && c == m->escape){
if(socklen(Curproc->input,0))
recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
break;
}
#ifdef MBXTDISC
if(c == '\n')
start_timer(&m->tdisc);
#endif
if(usputc(s,c) == EOF)
break;
}
stop_timer(&gwa->t);
free((char *)gwa);
close_s(s);
killproc(child); /* get rid of the receive process */
if(m->family == AF_INET)
tprintf("%c%c%c\n",IAC,WONT,TN_ECHO);
#ifdef TTYCALL
if (fsocket->sa_family == AF_INET &&
((struct sockaddr_in *) fsocket)->sin_port == IPPORT_TTYLINK &&
ismyaddr((int32)((struct sockaddr_in *) fsocket)->sin_addr.s_addr))
return 2; /* magic success code to avoid BBS chaining */
#endif
return 0;
}
void
gw_input(s,notused,p)
int s;
void *notused;
void *p;
{
int c;
struct proc *parent;
struct mbx *m;
char *cp, *cp1;
char response[4];
parent = (struct proc *) p;
m = (struct mbx *) notused;
cp1 = strdup(Mbnrid);
if((cp = strchr(cp1,'}')) != NULLCHAR)
*cp = '\0';
strupr(cp1);
#ifdef notdef
while((c = recvchar(s)) != EOF)
tputc(c);
#endif
while((c = recvchar(s)) != EOF){
if(c != IAC){
tputc((char)c);
continue;
}
/* IAC received, get command sequence */
c = recvchar(s);
switch(c){
case WILL:
response[0] = IAC;
response[1] = DONT;
response[2] = recvchar(s);
response[3] = '\0';
usputs(s,response);
break;
case WONT:
case DONT:
c = recvchar(s);
break;
case DO:
response[0] = IAC;
response[1] = WONT;
response[2] = recvchar(s);
response[3] = '\0';
usputs(s,response);
break;
case IAC: /* Escaped IAC */
usputc(s,IAC);
break;
}
}
if((cp = sockerr(s)) != NULLCHAR && m->family != AF_NETROM) {
switch(cp[0]) {
case 'T':
usprintf(m->user,"\n*** %s: Link failure",cp1);
break;
case 'R':
usprintf(m->user,"*** DM received");
break;
}
}
usprintf(m->user,"\n%s%seconnected to %s\n\n",
(m->family == AF_NETROM) ? Mbnrid : "",
(m->family == AF_NETROM) ? "R" : "*** r",
cp1);
free(cp1);
cp1 = NULLCHAR;
/* Tell the parent that we are no longer connected */
alert(parent,ENOTCONN);
pwait(Curproc); /* Now wait to be killed */
}
/* Check if the escape character is typed while the parent process is busy
* doing other things.
*/
void
gw_superv(null,proc,p)
int null;
void *proc;
void *p;
{
struct proc *parent;
struct mbx *m;
int c;
parent = (struct proc *) proc;
m = (struct mbx *) p;
while((c = recvchar(Curproc->input)) != EOF)
if(c == m->escape){
/* flush anything in the input queue */
if(socklen(Curproc->input,0))
recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
break;
}
alert(parent,EINTR); /* Tell the parent to quit */
pwait(Curproc); /* Please kill me */
}
void
gw_alarm(p)
void *p;
{
struct gwalarm *gwa = (struct gwalarm *)p;
char oldbl;
struct usock *up;
/* Flush sockets s1 and s2, but first make sure that the socket
* is set to non-blocking mode, to prevent the flush from blocking
* if the high water mark has been reached.
*/
if((up = itop(gwa->s1)) != NULLUSOCK) {
oldbl = up->noblock;
up->noblock = 1;
usflush(gwa->s1);
up->noblock = oldbl;
}
if((up = itop(gwa->s2)) != NULLUSOCK) {
oldbl = up->noblock;
up->noblock = 1;
usflush(gwa->s2);
up->noblock = oldbl;
}
start_timer(&gwa->t);
}
#ifdef MAILCMDS
/* States for send line parser state machine */
#define LOOK_FOR_USER 2
#define IN_USER 3
#define AFTER_USER 4
#define LOOK_FOR_HOST 5
#define IN_HOST 6
#define AFTER_HOST 7
#define LOOK_FOR_FROM 8
#define IN_FROM 9
#define AFTER_FROM 10
#define LOOK_FOR_MSGID 11
#define IN_MSGID 12
#define FINAL_STATE 13
#define ERROR_STATE 14
/* Prepare the addressee. If the address is bad, return -1, otherwise
* return 0
*/
int
#ifdef PROTOTYPES
mbx_to(int argc,char **argv,void *p)
#else
mbx_to(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
register char *cp;
int state, i;
char *user, *host, *from, *msgid;
int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0;
struct mbx *m;
m = (struct mbx *)p;
/* Free anything that might be allocated
* since the last call to mbx_to() or mbx_reply()
*/
free(m->to);
m->to = NULLCHAR;
free(m->tofrom);
m->tofrom = NULLCHAR;
free(m->tomsgid);
m->tomsgid = NULLCHAR;
free(m->origto);
m->origto = NULLCHAR;
free(m->origbbs);
m->origbbs = NULLCHAR;
free(m->subject);
m->subject = NULLCHAR;
free(m->date);
m->date = NULLCHAR;
if(argc == 1)
return -1;
#ifdef __GNUC__
user = 0; /* shut gcc warnings off */
host = 0;
from = 0;
msgid = 0;
#endif
i = 1;
cp = argv[i];
state = LOOK_FOR_USER;
while(state < FINAL_STATE){
#ifdef MBDEBUG
tprintf("State is %d, char is %c\n", state, *cp);
#endif
switch(state){
case LOOK_FOR_USER:
if(*cp == '@' || *cp == '<' || *cp == '$'){
state = ERROR_STATE; /* no user */
} else {
user = cp; /* point at start */
userlen++; /* start counting */
state = IN_USER;
}
break;
case IN_USER:
switch(*cp){
case '\0':
state = AFTER_USER; /* done with username */
break;
case '@':
state = LOOK_FOR_HOST; /* hostname should follow */
break;
case '<':
state = LOOK_FOR_FROM; /* from name should follow */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id should follow */
break;
default:
userlen++; /* part of username */
}
break;
case AFTER_USER:
switch(*cp){
case '@':
state = LOOK_FOR_HOST; /* hostname follows */
break;
case '<':
state = LOOK_FOR_FROM; /* fromname follows */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id follows */
break;
default:
state = ERROR_STATE;
}
break;
case LOOK_FOR_HOST:
if(*cp == '@' || *cp == '<' || *cp == '$'){
state = ERROR_STATE;
break;
}
if(*cp == '\0')
break;
host = cp;
hostlen++;
state = IN_HOST;
break;
case IN_HOST:
switch(*cp){
case '\0':
state = AFTER_HOST; /* found user@host */
break;
case '@':
state = ERROR_STATE; /* user@host@? */
break;
case '<':
state = LOOK_FOR_FROM; /* fromname follows */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id follows */
break;
default:
hostlen++;
}
break;
case AFTER_HOST:
switch(*cp){
case '@':
state = ERROR_STATE; /* user@host @ */
break;
case '<':
state = LOOK_FOR_FROM; /* user@host < */
break;
case '$':
state = LOOK_FOR_MSGID; /* user@host $ */
break;
default:
state = ERROR_STATE; /* user@host foo */
}
break;
case LOOK_FOR_FROM:
if(*cp == '@' || *cp == '<' || *cp == '$'){
state = ERROR_STATE;
break;
}
if(*cp == '\0')
break;
from = cp;
fromlen++;
state = IN_FROM;
break;
case IN_FROM:
switch(*cp){
case '\0':
state = AFTER_FROM; /* user@host <foo */
break;
case '<':
state = ERROR_STATE; /* user@host <foo< */
break;
case '$':
state = LOOK_FOR_MSGID; /* message id follows */
break;
default:
fromlen++;
}
break;
case AFTER_FROM:
switch(*cp){
case '@': /* user@host <foo @ */
case '<': /* user@host <foo < */
state = ERROR_STATE;
break;
case '$':
state = LOOK_FOR_MSGID; /* user@host <foo $ */
break;
default:
state = ERROR_STATE; /* user@host foo */
}
break;
case LOOK_FOR_MSGID:
if(*cp == '\0')
break;
msgid = cp;
msgidlen++;
state = IN_MSGID;
break;
case IN_MSGID:
if(*cp == '\0')
state = FINAL_STATE;
else
msgidlen++;
break;
default:
/* what are we doing in this state? */
state = ERROR_STATE;
}
if(*(cp) == '\0'){
++i;
if(i < argc)
cp = argv[i];
else break;
} else
++cp;
}
if(state == ERROR_STATE || state == LOOK_FOR_HOST
|| state == LOOK_FOR_FROM || state == LOOK_FOR_MSGID)
return -1; /* syntax error */
m->to = mallocw((unsigned)userlen + hostlen + 2);
strncpy(m->to, user, (unsigned)userlen);
m->to[userlen] = '\0';
if(hostlen){
m->to[userlen] = '@';
strncpy(m->to + userlen + 1, host, (unsigned)hostlen);
m->to[userlen + hostlen + 1] = '\0';
}
if(fromlen){
m->tofrom = mallocw((unsigned)fromlen + 1);
strncpy(m->tofrom, from, (unsigned)fromlen);
m->tofrom[fromlen] = '\0';
}
if(msgidlen){
m->tomsgid = mallocw((unsigned)msgidlen + 1);
strncpy(m->tomsgid, msgid, (unsigned)msgidlen);
m->tomsgid[msgidlen] = '\0';
}
return 0;
}
/* This opens the data file and writes the mail header into it.
* Returns 0 if OK, and -1 if not.
*/
int
#ifdef PROTOTYPES
mbx_data(struct mbx *m,struct list *cclist,char *extra)
#else
mbx_data(m,cclist,extra)
struct mbx *m;
struct list *cclist; /* list of carbon copy recipients */
char *extra; /* optional extra header lines */
#endif
{
time_t t;
struct list *ap;
int cccnt = 0;
#ifdef notdef
time(&t);
/*These 2 lines get added again when the smtp-server handles the mail
*not really needed - WG7J
*/
fprintf(m->tfile,Hdrs[RECEIVED]);
if(m->tofrom != NULLCHAR)
fprintf(m->tfile,"from %s ",m->name);
fprintf(m->tfile,"by %s (%s)\n\tid AA%ld ; %s",
Hostname, Version, get_msgid(),ptime(&t));
#endif
/* If m->date is set, use this one (comes from bbs-forwarded mail) */
if(m->date != NULLCHAR)
fprintf(m->tfile,"%s%s",Hdrs[DATE],m->date);
else {
time(&t);
fprintf(m->tfile,"%s%s",Hdrs[DATE],ptime(&t));
}
/* Bulletin ID, if any */
fprintf(m->tfile,Hdrs[MSGID]);
if(m->tomsgid)
fprintf(m->tfile,"<%s@%s.bbs>\n", m->tomsgid, m->name);
else
fprintf(m->tfile,"<%ld@%s>\n",get_msgid(), Hostname);
/* From : , could use 'real bbs address', if origbbs is set */
fprintf(m->tfile,Hdrs[FROM]);
if(m->tofrom) { /* BBS style '< call' */
if(m->origbbs != NULLCHAR)
fprintf(m->tfile,"%s@%s\n",m->tofrom,m->origbbs);
else
fprintf(m->tfile,"%s%%%s@%s\n",m->tofrom, m->name, Hostname);
} else {
if(m->origbbs != NULLCHAR)
fprintf(m->tfile,"%s@%s\n",m->name,m->origbbs);
else
fprintf(m->tfile,"%s@%s\n",m->name,Hostname);
}
fprintf(m->tfile,"%s%s\n",Hdrs[TO],m->origto != NULLCHAR ? m->origto : m->to);
/* Write Cc: line */
for(ap = cclist; ap != NULLLIST; ap = ap->next) {
if(cccnt == 0){
fprintf(m->tfile,"%s",Hdrs[CC]);
cccnt = 4;
}
else {
fprintf(m->tfile,", ");
cccnt += 2;
}
if(cccnt + strlen(ap->val) > 80 - 3) {
fprintf(m->tfile,"\n ");
cccnt = 4;
}
fputs(ap->val,m->tfile);
cccnt += strlen(ap->val);
}
if(cccnt)
fputc('\n',m->tfile);
fprintf(m->tfile,"%s%s\n",Hdrs[SUBJECT],m->subject);
if(!isspace(m->stype) && ((m->stype != 'R' && m->stype != 'F') ||
(m->sid & MBX_SID) !=0))
fprintf(m->tfile,"%s%c\n", Hdrs[BBSTYPE],m->stype);
#ifdef notdef
/*not really needed, the 'From <user%fwdbbs@host>' shows this too!*/
/* Also store the 'real smtp from' address */
if((m->tofrom != NULLCHAR) && (m->origbbs != NULLCHAR))
fprintf(m->tfile,"%s%s%%%s@%s\n",Hdrs[XFROM],m->tofrom,m->name, Hostname);
#endif
if(extra != NULLCHAR)
fprintf(m->tfile,extra);
return 0;
}
/* Returns true if string is in history file or if string appears to be a
* message id generated by our system.
*/
int
#ifdef PROTOTYPES
msgidcheck(char *string)
#else
msgidcheck(string)
char *string;
#endif
{
FILE *fp;
char buf[LINELEN], *cp;
if(string == NULLCHAR)
return 0;
/* BID's that we have generated ourselves are not kept in the history
* file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
* our hostname, truncated so that the BID is no longer than 11
* characters.
*/
if((cp = strchr(string,'_')) != NULLCHAR && *(cp+1) != '\0' &&
strnicmp(cp+1,Hostname,strlen(cp+1)) == 0)
return 1;
if((fp = fopen(Historyfile,READ_TEXT)) == NULLFILE)
return 0;
while(fgets(buf,LINELEN,fp) != NULLCHAR) {
rip(buf);
/* Get rid of following spaces or tabs, to separate the
* bid and it's time stamp entry - WG7J
*/
if( ((cp=strchr(buf,' ')) != NULLCHAR) || \
((cp=strchr(buf,'\t')) != NULLCHAR) )
*cp = '\0';
if(stricmp(string,buf) == 0) { /* found */
fclose(fp);
return 1;
}
}
fclose(fp);
return 0;
}
#endif /* MAILCMDS */
/* uuencode a file -- translated from C++; both versions copyright 1990
by David R. Evans, G4AMJ/NQ0I
*/
int
uuencode(infile,s,infilename)
FILE *infile;
int s; /* output socket */
char *infilename;
{
int n_read_so_far = 0, n_written_so_far = 0, in_chars, n, mode = 0755;
unsigned long cnt = 0;
unsigned char in[3], out[4], line[100];
#ifdef UNIX
struct stat stb;
if(stat(infilename,&stb) != -1)
mode = stb.st_mode & 0777; /* get real file protection mode */
#endif
usprintf(s, "begin %03o %s\n", mode, infilename);
/* do the encode */
for(;;){
in_chars = fread(in, 1, 3, infile);
out[0] = in[0] >> 2;
out[1] = in[0] << 6;
out[1] = out[1] >> 2;
out[1] = out[1] | (in[1] >> 4);
out[2] = in[1] << 4;
out[2] = out[2] >> 2;
out[2] = out[2] | (in[2] >> 6);
out[3] = in[2] << 2;
out[3] = out[3] >> 2;
for (n = 0; n < 4; n++)
out[n] += ' ';
n_read_so_far += in_chars;
for (n = 0; n < 4; n++)
line[n_written_so_far++] = out[n];
if (((in_chars != 3) || (n_written_so_far == 60)) && n_read_so_far > 0) {
line[(n_read_so_far + 2) / 3 * 4] = '\0';
usprintf(s,"%c%s\n",n_read_so_far + ' ', line);
cnt += n_read_so_far;
n_read_so_far = 0;
n_written_so_far = 0;
}
if (in_chars == 0)
break;
}
if (usprintf(s," \nend\nsize %lu\n", cnt) == EOF)
return 1;
return 0;
}
#ifdef MAILCMDS
/* Attempt to determine if this is third-pary mail. */
int
#ifdef PROTOTYPES
thirdparty(struct mbx *m)
#else
thirdparty(m)
struct mbx *m;
#endif
{
char buf[MBXLINE], *cp, *rp;
FILE *fp;
if(strchr(m->to,'@') != NULLCHAR || strchr(m->to,'%') != NULLCHAR
|| strchr(m->to,'!') != NULLCHAR)
return 0;
rp = strdup(Hostname);
if((cp = strchr(rp, '.')) != NULLCHAR)
*cp = '\0';
if(stricmp(m->to,rp) == 0){
free(rp);
return -1;
}
free(rp);
if(stricmp(m->to,"sysop") == 0)
return -1;
if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE)
return 0;
while(fgets(buf,MBXLINE,fp) != NULLCHAR){
/* The first word on each line is all that matters */
if((cp = strchr(buf, ' ')) != NULLCHAR)
*cp = '\0';
if((cp = strchr(buf,'\t')) != NULLCHAR)
*cp = '\0';
if(stricmp(m->to,buf) == 0){
fclose(fp);
return -1;
}
}
fclose(fp);
return 0;
}
#endif
extern int Mbconverse;
int
#ifdef PROTOTYPES
dombconnect(int argc,char **argv,void *p)
#else
dombconnect(argc,argv,p)
int argc;
char *argv[];
void *p;
#endif
{
struct mbx *m;
struct nrroute_tab *np;
int ndigis,i,s;
struct sockaddr_nr lsocket,fsocket;
struct sockaddr_ax alsocket; /*the local socket*/
struct sockaddr_ax afsocket; /*the remote socket*/
struct iface *ifp;
char alias[AXBUF];
char local_call[AXALEN];
char digis[MAXDIGIS][AXALEN];
char target[AXALEN];
m = (struct mbx *) p;
if(argc == 1){
#ifdef CONVERS
if(!Mbconverse) {
tputs("Convers server not enabled\n");
return 0;
}
if(m->privs & NO_CONVERS) {
tputs(Noperm);
mail_error("%s: converse denied\n",m->name);
return 0;
}
#ifdef GWTRACE
log(m->user,"MBOX CONVERS: %s",m->name);
#endif
m->state = MBX_CONVERS;
mbox_converse(m);
#else
dombconnecthelp();
#endif
return 0;
}
if(MBSecure)
#ifdef NETROM
if((m->family != AF_AX25) && (m->family != AF_NETROM)) {
#else
if(m->family != AF_AX25) {
#endif
tputs(Noperm);
mail_error("%s: gateway denied (secure mode)\n",m->name);
return 0;
}
if (argc == 2) {
#ifndef NETROM
dombconnecthelp();
return 0;
}
#else
/*NETROM connection wanted*/
if(!(m->privs & NETROM_CMD)) {
tputs(Noperm);
mail_error("%s: NETROM gate to %s denied\n",m->name,argv[1]);
return 0;
}
if(Nr_iface == NULLIF){
tputs("NET/ROM not activated.\n\n");
return 0;
}
/* See if the requested destination is a known alias or call,
* use it if it is. Otherwize give an error message.
*/
putalias(alias,argv[1],0);
strupr(argv[1]); /*make sure it's upper case*/
if((np = find_nrboth(alias,argv[1])) == NULLNRRTAB){
/*no such call or node alias*/
tputs("no such node\n\n");
dombconnecthelp();
dombports(0,NULL,p);
return 0;
}
if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
tputs(Nosock);
return 0;
}
#ifdef GWTRACE
log(m->user,"MBOX NETROM: %s to %s",m->name,argv[1]);
#endif
lsocket.nr_family = AF_NETROM;
/* Set up our local username, bind would use Mycall instead */
memcpy(lsocket.nr_addr.user,m->call,AXALEN);
/* Set up our source address */
memcpy(lsocket.nr_addr.node,Nr_iface->hwaddr,AXALEN);
bind(s,(char *)&lsocket,sizeof(struct sockaddr_nr));
memcpy(fsocket.nr_addr.user,np->call,AXALEN);
memcpy(fsocket.nr_addr.node,np->call,AXALEN);
fsocket.nr_family = AF_NETROM;
m->state = MBX_GATEWAY;
return gw_connect(m,s,(struct sockaddr *)&fsocket, sizeof(struct sockaddr_nr));
}
#endif /*NETROM*/
#ifdef AX25
if(argc > 2) {
/*AX25 gateway connection wanted*/
if(!(m->privs & AX25_CMD)) {
tputs(Noperm);
mail_error("%s: AX.25 gate to %s on %s denied\n",m->name,argv[2],argv[1]);
return 0;
}
if( ((ifp = if_lookup(argv[1])) == NULLIF) ||
((ifp->flags & HIDE_PORT) && !(m->privs & SYSOP_CMD)) ||
(ifp->type != CL_AX25) ) {
tprintf("Unknown port %s\n",argv[1]);
dombports(0,NULL,p);
return 0;
}
if(setcall(target,argv[2]) == -1){
tprintf("Bad call %s\n",argv[2]);
return 0;
}
/* If digipeaters are given, put them in the routing table */
if(argc > 3){
ndigis = argc - 3;
if(ndigis > MAXDIGIS){
tputs("Too many digipeaters\n");
return 0;
}
for(i=0;i<ndigis;i++){
if(setcall(digis[i],argv[i+3]) == -1){
tprintf("Bad digipeater %s\n",argv[i+3]);
return 0;
}
}
if(ax_add(target,AX_AUTO,digis,ndigis,ifp) == NULLAXR){
tputs("AX25 route add failed\n");
return 0;
}
}
if((s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
tputs(Nosock);
return 0;
}
#ifdef GWTRACE
log(m->user,"MBOX AX25: %s to %s on %s",m->name,argv[2],argv[1]);
#endif
/*fill in the known stuff*/
alsocket.sax_family = afsocket.sax_family= AF_AX25;
/*the remote call to connect to*/
setcall(afsocket.ax25_addr,argv[2]);
/*the outgoing interface*/
strncpy(afsocket.iface,argv[1],ILEN);
/*now set local user call, invert ssid*/
memcpy(local_call,m->call,AXALEN);
local_call[AXALEN-1] ^= 0x1e;
memcpy(alsocket.ax25_addr,local_call,AXALEN);
/*and bind it (otherwize Mycall will be used!)*/
bind(s,(char *)&alsocket,sizeof(struct sockaddr_ax));
m->state = MBX_GATEWAY;
return gw_connect(m,s,(struct sockaddr *)&afsocket, sizeof(struct sockaddr_ax));
}
#endif /* AX25 */
return 0;
}
#endif /* MAILBOX */